Bug 4779253

Bug Description:

This is a race bug.
This bug is very hard to reproduce because its buggy window is very narrow. So a short pause is added to the buggy source's byte code to extend the window.
More details about this bug are at JDK-4779253 JIRA page.

Interleaving Description:

java.util.logging.Logger

t1  t2  public void log(LogRecord record) {
            if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
                return;
            }
            synchronized (this) {
1,3             if (filter != null && !filter.isLoggable(record)) {
                    return;
                }
            }
        }
            
        public void setFilter(Filter newFilter) throws SecurityException {
            checkAccess();
    2       filter = newFilter;
        }

Precondition:
filter has been initialized to some instance.
a) thread 1 enters synchronized block to check if filter is null at 1. As mentioned in precondition, filter is not null,so it continues to check the second condition.
b) just before thread 1 starts to check the second condition, context switched, thread 2 set filter to newFilter at 2. Although line 1 is protected by synchronized block, there is no such protection at line 2, filter is still free to alter at 2. Here newFilter is null, and filter is set to null.
c) context switched, thread 1 continues to check the second condition after "&&". But now filter is null, so a NullpointerException is thrown out.


How To Reproduce:

This bug is reproduced under JDK 1.6.0 and JDK 1.6.0_33.
It started at JDK 1.6.0, and has been fixed since JDK 1.7.0.
Execute the following scripts to run the test to reproduce the bug (assume the location of the jdk6 test project is jdk_test_home).

Linux:
${jdk_test_home}/scripts/4779253.sh [--javaloc path] [--sleepTime value]
Windows:
%jdk_test_home%\scripts\4779253.bat [--javaloc path] [--sleepTime value]

Example:
The default number of sleepTime is 1000 if not specified. For example:
${jdk_test_home}/scripts/4779253.sh
is the same as:
${jdk_test_home}/scripts/4779253.sh --sleepTime 1000

Option Function
--sleepTime, -st milliseconds to sleep between two condition checks where race could happen. Default value is 1000 if this option is not set explicitly.
--javaloc The location of JDK that is eligible to reproduce the bug, if your java environment is not eligible.
In this case, it's JDK 1.6.0. It should be the absolute path to the JDK's java starter and ended with "/".
For example: ~/jdk/home/jdk1.6.0/bin/